package app.itgungnir.compose.wan.business.main.agenda

import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import app.itgungnir.compose.wan.utils.*
import com.google.gson.JsonElement
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow

class AgendaViewModel : ViewModel() {

    val loadingState = MutableStateFlow(false)
    val dialogLoadingState = MutableStateFlow(false)
    val errorState = MutableSharedFlow<Throwable?>()
    val dialogErrorState = MutableSharedFlow<Throwable?>()
    val dismissDialogState = MutableStateFlow(false)
    var loadingJob: Job? = null
    var dialogLoadingJob: Job? = null

    val statusState = mutableStateOf<Int?>(null)
    val typeState = mutableStateOf<Int?>(null)
    val priorityState = mutableStateOf<Int?>(null)
    val orderByState = mutableStateOf<Int?>(4)

    val agendaListFlow = pagingSourceWithCache(
        firstPageIndex = 1,
        pageSize = 20,
        networkRequest = {
            wanAndroidService.getAgendaList(
                pageNo = it,
                status = statusState.value,
                type = typeState.value,
                priority = priorityState.value,
                orderby = orderByState.value
            ).wanResponse()
        },
        queryCache = { dao ->
            when (orderByState.value) {
                1 -> dao.queryAgendasByCompleteDateAsc()
                2 -> dao.queryAgendasByCompleteDateDesc()
                3 -> dao.queryAgendasByDateAsc()
                else -> dao.queryAgendasByDateDesc()
            }
        },
        clearCache = { dao -> dao.deleteAllAgendas() },
        appendCache = { list, dao -> dao.insertAllAgendas(list) }
    )

    fun addAgenda(title: String, content: String, date: String? = null, type: Int?, priority: Int?) {
        dialogLoadingJob = launch(loadingState = dialogLoadingState, errorState = dialogErrorState) {
            dismissDialogState.emit(false)
            if (title.isEmpty()) {
                throw IllegalArgumentException("标题不能为空")
            }
            if (content.isEmpty()) {
                throw IllegalArgumentException("内容不能为空")
            }
            val response = wanAndroidService.addAgenda(title.encode(), content.encode(), date, type, priority)
                .wanResponse<Agenda>()
            response?.takeIf {
                (it.type == typeState.value || typeState.value == null) &&
                        (it.priority == priorityState.value || priorityState.value == null) &&
                        (it.status == statusState.value || statusState.value == null)
            }?.let { agenda ->
                WanDatabase.dao.insertAgenda(agenda)
            }
            dismissDialogState.emit(true)
        }
    }

    fun updateAgenda(agenda: Agenda) = launch(loadingState = dialogLoadingState, errorState = dialogErrorState) {
        dismissDialogState.emit(false)
        if (agenda.title.isNullOrEmpty()) {
            throw IllegalArgumentException("标题不能为空")
        }
        if (agenda.content.isNullOrEmpty()) {
            throw IllegalArgumentException("内容不能为空")
        }
        wanAndroidService.updateAgenda(
            agendaId = agenda.id,
            title = agenda.title.encode(),
            content = agenda.content.encode(),
            date = agenda.dateStr,
            status = agenda.status,
            type = agenda.type,
            priority = agenda.priority
        ).wanResponse<JsonElement>()
        if ((agenda.type == typeState.value || typeState.value == null) &&
            (agenda.priority == priorityState.value || priorityState.value == null) &&
            (agenda.status == statusState.value || statusState.value == null)
        ) {
            WanDatabase.dao.updateAgenda(agenda.copy(title = agenda.title.encode(), content = agenda.content.encode()))
        } else {
            WanDatabase.dao.deleteAgenda(agenda.id)
        }
        dismissDialogState.emit(true)
    }.also { dialogLoadingJob = it }

    fun updateAgendaStatus(agenda: Agenda) = launch(loadingState = loadingState, errorState = errorState) {
        wanAndroidService.updateAgendaStatus(agendaId = agenda.id, status = agenda.status).wanResponse<JsonElement>()
        if (statusState.value == null) {
            val currentMillis = System.currentTimeMillis()
            WanDatabase.dao.updateAgenda(
                agenda.copy(
                    title = agenda.title.encode(),
                    content = agenda.content.encode(),
                    status = agenda.status,
                    completeDate = if (agenda.status == 1) currentMillis else 0L,
                    completeDateStr = if (agenda.status == 1) currentMillis.toDateString() else null
                )
            )
        } else {
            WanDatabase.dao.deleteAgenda(agenda.id)
        }
    }.also { loadingJob = it }

    fun deleteAgenda(id: Long) = launch(loadingState = loadingState, errorState = errorState) {
        wanAndroidService.deleteAgenda(id).wanResponse<JsonElement>()
        WanDatabase.dao.deleteAgenda(id)
    }.also { loadingJob = it }
}
